package self.zhangkang.chart.tools

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import android.os.Build
import self.zhangkang.chart.view.IndexNameConfig
import self.zhangkang.chart.view.pool.RectPool

/**
 * @author : Android-张康
 * created on: 2023/5/9 18:52
 * description: 绘制工具类
 */
object CanvasTools {

    /**
     * 将文字绘制中竖直的中间
     *
     * @param canvas 画布
     * @param startX 开始的 X 坐标
     * @param startY 开始的 Y 坐标
     * @param stopY 介绍的 Y 坐标
     * @param text 需要绘制的文字
     * @param textPaint 文字的画笔
     * @param rectPool [RectF] 对象池
     *
     * @return 绘制文字的宽度
     */
    internal fun drawTextInVerticalCenter(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopY: Float,
        text: String,
        textPaint: Paint,
        rectPool: RectPool
    ): Int {
        val textBoundsRect = rectPool.acquire()
        textPaint.getTextBounds(text, 0, text.length, textBoundsRect)
        val textY =
            startY + (stopY - startY - textBoundsRect.height()) / 2 + textBoundsRect.height()
        canvas.drawText(text, startX, textY, textPaint)
        rectPool.release(textBoundsRect)
        return textBoundsRect.width()
    }

    /**
     * 绘制指标名称
     *
     * @param canvas 画布
     * @param startX 矩形的左坐标
     * @param startY 开始的 Y 坐标
     * @param stopY 介绍的 Y 坐标
     * @param linePaint 线的画笔
     * @param textPaint 文字的画笔
     * @param rectPool [RectF] 对象池
     * @param indicatorName 指标的名称
     * @param indexNameConfig 指标名称的配置
     *
     * @return 返回指标名称的宽度
     */
    internal fun drawIndicatorName(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopY: Float,
        linePaint: Paint,
        textPaint: Paint,
        rectPool: RectPool,
        indicatorName: String,
        indexNameConfig: IndexNameConfig,
        hasArrowDropDown: Boolean = true,
    ): Float {
        val arrowDropDownBitmap = indexNameConfig.arrowDropDownBitmap
        val drawArrow = hasArrowDropDown && null != arrowDropDownBitmap

        //先获取文字的宽高
        textPaint.textSize = indexNameConfig.textSize
        textPaint.color = indexNameConfig.textColor
        val textBoundsRect = rectPool.acquire()
        textPaint.getTextBounds(indicatorName, 0, indicatorName.length, textBoundsRect)

        //背景的信息
        val rectLeft = startX + indexNameConfig.marginStart
        var rectRight =
            rectLeft + indexNameConfig.paddingHorizontal + textBoundsRect.width() + indexNameConfig.paddingHorizontal
        //如果绘制箭头，需要加上箭头的宽度和间距
        if (drawArrow) {
            rectRight += indexNameConfig.arrowDropDownWidth + indexNameConfig.paddingHorizontal
        }
        val drawHeight = textBoundsRect.height() + indexNameConfig.paddingVertical * 2
        val rectTop = startY + (stopY - startY - drawHeight) / 2
        val rectBottom = rectTop + drawHeight
        //绘制背景
        linePaint.style = Paint.Style.FILL
        linePaint.color = indexNameConfig.backgroundColor
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            canvas.drawRoundRect(
                rectLeft,
                rectTop,
                rectRight,
                rectBottom,
                indexNameConfig.radius,
                indexNameConfig.radius,
                linePaint
            )
        } else {
            val rectF = RectF(
                rectLeft,
                rectTop,
                rectRight,
                rectBottom,
            )
            canvas.drawRoundRect(
                rectF,
                indexNameConfig.radius,
                indexNameConfig.radius,
                linePaint
            )
        }
        //绘制描边
        linePaint.style = Paint.Style.STROKE
        linePaint.strokeWidth = indexNameConfig.strokeWidth
        linePaint.color = indexNameConfig.strokeColor
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            canvas.drawRoundRect(
                rectLeft,
                rectTop,
                rectRight,
                rectBottom,
                indexNameConfig.radius,
                indexNameConfig.radius,
                linePaint
            )
        } else {
            val rectF = RectF(
                rectLeft,
                rectTop,
                rectRight,
                rectBottom,
            )
            canvas.drawRoundRect(
                rectF,
                indexNameConfig.radius,
                indexNameConfig.radius,
                linePaint
            )
        }
        //绘制文字
        val height = stopY - startY
        val textHeight = textBoundsRect.height()
        val textTop = startY + (height - indexNameConfig.strokeWidth * 2 - textHeight) / 2
        val textX = rectLeft + indexNameConfig.paddingHorizontal
        val textY = textTop + textHeight
        canvas.drawText(indicatorName, textX, textY, textPaint)
        //绘制箭头
        if (drawArrow && null != arrowDropDownBitmap) {
            val bitmapTop = startY + (height - arrowDropDownBitmap.height) / 2
            canvas.drawBitmap(
                arrowDropDownBitmap,
                rectLeft + indexNameConfig.paddingHorizontal + textBoundsRect.width() + indexNameConfig.paddingHorizontal,
                bitmapTop,
                linePaint
            )
        }
        rectPool.release(textBoundsRect)
        return rectRight - startX
    }

    fun getDrawTextBounds(
        startX: Float,
        startY: Float,
        stopY: Float,
        textPaint: Paint,
        indicatorName: String,
        indexNameConfig: IndexNameConfig,
        textBoundsRect: Rect,
        hasArrowDropDown: Boolean = true,
    ) {
        val arrowDropDownBitmap = indexNameConfig.arrowDropDownBitmap
        val drawArrow = hasArrowDropDown && null != arrowDropDownBitmap

        //先获取文字的宽高
        textPaint.textSize = indexNameConfig.textSize
        textPaint.color = indexNameConfig.textColor
        textPaint.getTextBounds(indicatorName, 0, indicatorName.length, textBoundsRect)
        //背景的信息
        val rectLeft = startX + indexNameConfig.marginStart
        var rectRight =
            rectLeft + indexNameConfig.paddingHorizontal + textBoundsRect.width() + indexNameConfig.paddingHorizontal
        //如果绘制箭头，需要加上箭头的宽度和间距
        if (drawArrow) {
            rectRight += indexNameConfig.arrowDropDownWidth + indexNameConfig.paddingHorizontal
        }
        val drawHeight = textBoundsRect.height() + indexNameConfig.paddingVertical * 2
        val rectTop = startY + (stopY - startY - drawHeight) / 2
        val rectBottom = rectTop + drawHeight
        textBoundsRect.set(rectLeft.toInt(), rectTop.toInt(), rectRight.toInt(), rectBottom.toInt())
    }

    /**
     * 绘制高亮底部信息
     *
     * @param canvas 画布
     * @param startX 开始的 X 坐标
     * @param stopX 结束的 X 坐标
     * @param startY 开始的 Y 坐标
     * @param stopY 结束的 Y 坐标
     * @param longPressX 长按的 X 坐标
     * @param longPressY 长按的 Y 坐标
     * @param textStartY 文字开始绘制的 Y 坐标
     * @param rectPool [RectF] 对象池
     * @param drawText 需要绘制的文字
     * @param textPaint 文字绘制的画笔
     * @param backgroundColor 背景的颜色
     * @param textSize 文字的大小
     * @param textColor 文字的颜色
     * @param isLeft 是否为左边
     */
    fun drawHighlightLeftOrRightValue(
        canvas: Canvas,
        startX: Float,
        stopX: Float,
        startY: Float,
        stopY: Float,
        longPressX: Float,
        longPressY: Float,
        textStartY: Float,
        rectPool: RectPool,
        drawText: String,
        textPaint: Paint,
        backgroundColor: Int,
        textSize: Float,
        textColor: Int,
        isLeft: Boolean
    ) {
        textPaint.textSize = textSize
        val textBoundsRect = rectPool.acquire()
        textPaint.getTextBounds(drawText, 0, drawText.length, textBoundsRect)
        val currentDateX = if (isLeft) {
            startX
        } else {
            stopX - textBoundsRect.width()
        }
        val currentDateY = longPressY + textBoundsRect.height() / 2

        textPaint.color = backgroundColor
        canvas.drawRect(
            currentDateX - 2,
            currentDateY - textBoundsRect.height() - 3,
            currentDateX + textBoundsRect.width() + 3,
            currentDateY + 2,
            textPaint
        )
        textPaint.textSize = textSize
        textPaint.color = textColor
        canvas.drawText(drawText, currentDateX, currentDateY, textPaint)
        rectPool.release(textBoundsRect)
    }

    /**
     * 绘制高亮底部信息
     *
     * @param canvas 画布
     * @param startX 开始的 X 坐标
     * @param stopX 结束的 X 坐标
     * @param startY 开始的 Y 坐标
     * @param stopY 结束的 Y 坐标
     * @param longPressX 长按的 X 位置
     * @param textStartY 文字开始绘制的 Y 坐标
     * @param rectPool [RectF] 对象池
     * @param drawText 需要绘制的文字
     * @param textPaint 文字绘制的画笔
     * @param backgroundColor 背景的颜色
     * @param textSize 文字的大小
     * @param textColor 文字的颜色
     */
    fun drawHighlightBottomValue(
        canvas: Canvas,
        startX: Float,
        stopX: Float,
        startY: Float,
        stopY: Float,
        longPressX: Float,
        textStartY: Float,
        rectPool: RectPool,
        drawText: String,
        textPaint: Paint,
        backgroundColor: Int,
        textSize: Float,
        textColor: Int,
        textPaddingHorizontal: Float
    ) {
        val textBoundsRect = rectPool.acquire()
        textPaint.getTextBounds(drawText, 0, drawText.length, textBoundsRect)
        var currentDateX = longPressX - textBoundsRect.width() / 2 - textPaddingHorizontal
        if (currentDateX < startX) {
            currentDateX = startX
        }
        var currentDateEndX = currentDateX + textBoundsRect.width() + textPaddingHorizontal * 2
        if (currentDateEndX > stopX) {
            currentDateEndX = stopX
            currentDateX = currentDateEndX - textBoundsRect.width() - textPaddingHorizontal * 2
        }
        val currentDateY = textStartY + textBoundsRect.height()
        textPaint.color = backgroundColor
        canvas.drawRect(
            currentDateX,
            currentDateY - textBoundsRect.height() - 3,
            currentDateEndX,
            currentDateY + 2,
            textPaint
        )
        textPaint.textSize = textSize
        textPaint.color = textColor
        val textX = currentDateX + textPaddingHorizontal
        canvas.drawText(drawText, textX, currentDateY, textPaint)
        rectPool.release(textBoundsRect)
    }
}